package com.ajk.server.service.impl;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ajk.message.model.BaseModel;
import com.ajk.server.controller.events.RemoteSyncEvent;
import com.ajk.server.dao.PatientEventDayMapper;
import com.ajk.server.dao.PatientEventExtMapper;
import com.ajk.server.dao.PatientEventMapper;
import com.ajk.server.dao.UsersMapper;
import com.ajk.server.exception.AjkException;
import com.ajk.server.exception.ErrorConstant;
import com.ajk.server.model.NurseStationDict;
import com.ajk.server.model.PatientEvent;
import com.ajk.server.model.PatientEventDay;
import com.ajk.server.model.PatientEventExt;
import com.ajk.server.model.query.PatientEventQuery;
import com.ajk.server.model.request.PatientEventCategory;
import com.ajk.server.model.response.UserRes;
import com.ajk.server.service.PatientEventDayService;
import com.ajk.server.service.PatientEventService;
import com.ajk.server.utils.AjkUtil;
import com.ajk.server.utils.FileStoreUtil;
import com.ajk.server.utils.HttpClientUtil;
import com.ajk.server.utils.RedisKeyUtil;
import com.ajk.server.utils.SpringContextUtil;
import com.ajk.server.utils.ThreadLocalSimpleDateFormater;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;

/**
 * 用户健康数据  <br>
 * t_patient_event <br>
 * v1.0 2016-05-01
 */
@Service
public class PatientEventServiceImpl implements PatientEventService {

	private static final Logger logger = LoggerFactory.getLogger(PatientEventServiceImpl.class);

	@Autowired
	private PatientEventMapper patientEventMapper;

	@Autowired
	PatientEventExtMapper patientEventExtMapper;

	@Autowired
	PatientEventDayService patientEventDayService;
	@Autowired
	PatientEventDayMapper patientEventDayMapper;

	@Autowired
	RedisTemplate<String,Object> template;
	
	@Autowired
	UsersMapper usersMapper;
	
	@Autowired
	Environment evn;

	/**
	 *根据ID删除 用户健康数据
	 */
	@Override
	public Integer deletePatientEventById(Integer id){
		return patientEventMapper.deleteById(id);
	}

	/**
	 *新增 用户健康数据
	 */
	@Override
	@Transactional
	public Integer batchInsertPatientEvent(List<? extends PatientEvent> patientEvents){
		Integer count = patientEventMapper.batchInsert(patientEvents);
		return count;
	}
	/**
	 *新增 用户健康数据
	 */
	@Override
	@Transactional
	public Integer insertPatientEvent(PatientEventDay patientEvent){
		Integer newPEId = null;
		
		Integer userId = patientEvent.getUserId();
		String content = patientEvent.getContent();
		String uuid = patientEvent.getUuid();
		Integer categoryId = patientEvent.getCategoryId();

		PatientEvent pe = patientEventMapper.findByUuidAndUserId(uuid,userId);

		if(pe!=null){
			AjkException exception = new AjkException(ErrorConstant.OPERATION_ERROR.getErrorCode(),"uuid("+uuid+")，userId("+userId+")对应的数据已经存在，不能添加");
			logger.info("添加健康数据",exception);
			throw exception;
		}

		patientEventMapper.insert(patientEvent);
		
		Integer patientEventId = patientEvent.getId();

		newPEId = patientEventId;
		
		PatientEventExt ext = new PatientEventExt();
		ext.setParentId(patientEventId);
		ext.setCategoryId(categoryId);
		JSONObject contentJson = com.alibaba.fastjson.JSON.parseObject(content);
		//		com.alibaba.fastjson.JSON.parseArray(content, Map.class);
		switch (categoryId) {
		case 1:
			Double bloodOxygen = contentJson.getDouble("bloodOxygen");
			ext.setBloodOxygen(bloodOxygen);
			break;
		case 2:
			Double systolicPressure = contentJson.getDouble("systolicPressure");
			Double diastolicPressure = contentJson.getDouble("diastolicPressure");
			ext.setSystolicPressure(systolicPressure);
			ext.setDiastolicPressure(diastolicPressure);
			break;
		case 3:
			Integer timeBlockId = contentJson.getInteger("timeBlockId");
			Double bloodSugar = contentJson.getDouble("bloodSugar");
			ext.setBloodSugar(bloodSugar);
			ext.setTimeBlockId(timeBlockId);
			break;
		case 4:
			Double temperature = contentJson.getDouble("temperature");
			ext.setTemperature(temperature);
			break;
		case 5:
			Integer heartRate = contentJson.getInteger("heartRate");
			ext.setHeartRate(heartRate);
			break;
		case 6:
			Integer bodyAge = contentJson.getInteger("bodyAge");
			ext.setBodyAge(bodyAge);
			break;
		default:
			AjkException exception = new AjkException(ErrorConstant.OPERATION_ERROR.getErrorCode(),"categoryId 超出范围");
			logger.info("添加健康数据",exception);
			throw exception;
		}
		patientEventExtMapper.insert(ext);

		//按照categoryId和actionTime查询当天是否已经有数据了

		//放入patient_event_day
		patientEvent.setPatientEventId(patientEventId);
		patientEvent.setId(null);
		patientEventDayService.insertPatientEventDay(patientEvent);
		
		RemoteSyncEvent event = new RemoteSyncEvent(newPEId, RemoteSyncEvent.SYNC_HEALTHY_DATA);
		SpringContextUtil.getApplicationContext().publishEvent(event);

		return patientEventId;
	}

	/**
	 *更新 用户健康数据
	 */
	@Override
	@Transactional
	public Integer updatePatientEvent(PatientEventDay patientEvent){
		Integer userId = patientEvent.getUserId();
		Integer id = patientEvent.getId();
		PatientEventDay db = patientEventDayMapper.findById(id);
		if(db==null){
			AjkException exception = new AjkException(ErrorConstant.OPERATION_ERROR.getErrorCode(),"修改的数据不存在");
			logger.info("添加健康数据",exception);
			throw exception;
		}

		if(db.getUserId().intValue()!=userId.intValue()){
			AjkException exception = new AjkException(ErrorConstant.OPERATION_ERROR.getErrorCode(),"无权限修改别人的健康数据");
			logger.info("添加健康数据",exception);
			throw exception;
		}

		Integer patientEventId = db.getPatientEventId();
		patientEvent.setId(patientEventId);
		patientEventMapper.update(patientEvent);
		patientEvent.setId(id);
		PatientEventExt ext = patientEventExtMapper.findByParentId(patientEventId);
		boolean isExists = true;
		if(ext == null){
			ext = new PatientEventExt();
			isExists = false;
		}
		Integer categoryId = db.getCategoryId();
		String content = patientEvent.getContent();
		if(StringUtils.isEmpty(content)){
			content = db.getContent();
		}
		ext.setParentId(patientEventId);
		ext.setCategoryId(categoryId);
		JsonObject contentJson = BaseModel.gson.fromJson(content, JsonObject.class);
		switch (categoryId) {
		case 1:
			Double bloodOxygen = contentJson.get("bloodOxygen").getAsDouble();
			ext.setBloodOxygen(bloodOxygen);
			break;
		case 2:
			Double systolicPressure = contentJson.get("systolicPressure").getAsDouble();
			Double diastolicPressure = contentJson.get("diastolicPressure").getAsDouble();
			ext.setSystolicPressure(systolicPressure);
			ext.setDiastolicPressure(diastolicPressure);
			break;
		case 3:
			Integer timeBlockId = contentJson.get("timeBlockId").getAsInt();
			Double bloodSugar = contentJson.get("bloodSugar").getAsDouble();
			ext.setBloodSugar(bloodSugar);
			ext.setTimeBlockId(timeBlockId);
			break;
		case 4:
			Double temperature = contentJson.get("temperature").getAsDouble();
			ext.setTemperature(temperature);
			break;
		case 5:
			Integer heartRate = contentJson.get("heartRate").getAsInt();
			ext.setHeartRate(heartRate);
			break;
		case 6:
			Integer bodyAge = contentJson.get("bodyAge").getAsInt();
			ext.setBodyAge(bodyAge);
			break;
		default:
			AjkException exception = new AjkException(ErrorConstant.OPERATION_ERROR.getErrorCode(),"categoryId 超出范围");
			logger.info("添加健康数据",exception);
			throw exception;
		}
		if(isExists){
			patientEventExtMapper.update(ext);
		}else{
			patientEventExtMapper.insert(ext);
		}


		patientEvent.setPatientEventId(patientEventId);
		patientEvent.setId(id);
		patientEventDayService.updatePatientEventDay(patientEvent);

		return id;
	}

	/**
	 *根据ID查询 用户健康数据
	 */
	public PatientEvent findPatientEventById(Integer id){
		PatientEvent result = patientEventMapper.findById(id);
		if(result!=null){
			result.dealWith();
		}
		return result;
	}

	/**
	 *通过query 查询 用户健康数据
	 */
	public List<PatientEvent> findPatientEventByQuery(PatientEventQuery query){
		query.dealWith();
		List<PatientEvent> result = patientEventMapper.findByQuery(query);
		if(CollectionUtils.isNotEmpty(result)) {
			Collections.sort(result);
			for (PatientEvent patientEvent : result) {
				patientEvent.dealWith();
			}
		}
		return result;
	}

	/**
	 *通过query count总条数
	 */
	public Integer countPatientEventByQuery(PatientEventQuery query){
		query.dealWith();
		Integer result = patientEventMapper.countByQuery(query);
		return result;
	}

	/**
	 * 通过ids查询
	 */
	public List<PatientEvent> findPatientEventByIds(List<Integer> ids){
		List<PatientEvent> result = patientEventMapper.findByIds(ids);
		if(CollectionUtils.isNotEmpty(result)) {
			for (PatientEvent patientEvent : result) {
				patientEvent.dealWith();
			}
		}
		return result;
	}

	/**
	 * 获取最近的健康数据
	 * 
	 */
	@Override
	public Map<String, PatientEventDay> findMyLastPatient(Integer userId) {
		String key = RedisKeyUtil.userLastPatientEventMapKey(userId);
		Map<String, PatientEventDay> map = new HashMap<String, PatientEventDay>();
		HashOperations<String, String, PatientEventDay> hashOperations = template.opsForHash();
		if(template.hasKey(key)){
			map = hashOperations.entries(key);
			if(map.get(PatientEventCategory.BLOOD_OXYGEN.name())==null){
				map.remove(PatientEventCategory.BLOOD_OXYGEN.name());
			}
			if(map.get(PatientEventCategory.BLOOD_PRESSURE.name())==null){
				map.remove(PatientEventCategory.BLOOD_PRESSURE.name());
			}
			if(map.get(PatientEventCategory.BLOOD_SUGAR.name())==null){
				map.remove(PatientEventCategory.BLOOD_SUGAR.name());
			}
			if(map.get(PatientEventCategory.BLOOD_SUGAR.name()+"_2")==null){
				map.remove(PatientEventCategory.BLOOD_SUGAR.name()+"_2");
			}
			if(map.get(PatientEventCategory.BODY_AGE.name())==null){
				map.remove(PatientEventCategory.BODY_AGE.name());
			}
			if(map.get(PatientEventCategory.HEART_RATE.name())==null){
				map.remove(PatientEventCategory.HEART_RATE.name());
			}
			if(map.get(PatientEventCategory.TEMPERATURE.name())==null){
				map.remove(PatientEventCategory.TEMPERATURE.name());
			}
		}else{
			PatientEventDay BLOOD_OXYGEN = patientEventDayMapper.findLastByCategoryId(userId,PatientEventCategory.BLOOD_OXYGEN.getValue());
			PatientEventDay BLOOD_PRESSURE = patientEventDayMapper.findLastByCategoryId(userId,PatientEventCategory.BLOOD_PRESSURE.getValue());
			PatientEventDay BLOOD_SUGAR = patientEventDayMapper.findLastSugarByCategoryId(userId,1);
			PatientEventDay BLOOD_SUGAR_2 = patientEventDayMapper.findLastSugarByCategoryId(userId,2);
			PatientEventDay BODY_AGE = patientEventDayMapper.findLastByCategoryId(userId,PatientEventCategory.BODY_AGE.getValue());
			PatientEventDay HEART_RATE = patientEventDayMapper.findLastByCategoryId(userId,PatientEventCategory.HEART_RATE.getValue());
			PatientEventDay TEMPERATURE = patientEventDayMapper.findLastByCategoryId(userId,PatientEventCategory.TEMPERATURE.getValue());

			
			if(BLOOD_OXYGEN!=null){
				map.put(PatientEventCategory.BLOOD_OXYGEN.name(), BLOOD_OXYGEN);
			}

			if(BLOOD_PRESSURE!=null)
				map.put(PatientEventCategory.BLOOD_PRESSURE.name(), BLOOD_PRESSURE);

			if(BLOOD_SUGAR!=null)
				map.put(PatientEventCategory.BLOOD_SUGAR.name(), BLOOD_SUGAR);

			if(BLOOD_SUGAR_2!=null)
				map.put(PatientEventCategory.BLOOD_SUGAR.name()+"_2", BLOOD_SUGAR_2);

			if(BODY_AGE!=null)
				map.put(PatientEventCategory.BODY_AGE.name(), BODY_AGE);

			if(HEART_RATE!=null)
				map.put(PatientEventCategory.HEART_RATE.name(), HEART_RATE);

			if(TEMPERATURE!=null)
				map.put(PatientEventCategory.TEMPERATURE.name(), TEMPERATURE);

			template.opsForHash().putAll(key,map);
			//			template.expire(key, 7, TimeUnit.DAYS);
		}
		return map;
	}
	
	@Override
	public JSONObject syncInRemote(Integer id) {
		logger.info("=========================准备同步健康数据(id={})======================",id);
		JSONObject obj = null;
		PatientEvent dict =  patientEventMapper.findById(id);
		if(dict!=null){
			String valicode= AjkUtil.getVaildate();
			Integer userId = dict.getUserId();
			Integer categoryId = dict.getCategoryId();
			String content = dict.getContent();
			
			UserRes userRes = usersMapper.findById(userId);
			if(userRes==null){
				return null;
			}
			String vipcodecard = userRes.getVipcodecard();
			
			if(StringUtils.isEmpty(vipcodecard)){
				logger.info("用户未同步，不许要同步健康数据");
				return null;
			}
			
			if(StringUtils.isEmpty(content) || categoryId==null){
				return null;
			}
			JsonObject contentJson = BaseModel.gson.fromJson(content, JsonObject.class);
			HashMap<String, Object> parameterMap = new HashMap<String, Object>();
			String url = null;
			try {
				parameterMap.put("vipcodecard", vipcodecard);
				parameterMap.put("source", "app");
				parameterMap.put("vipcodecard", vipcodecard);
				parameterMap.put("sourceAcount", userRes.getMobile());
				switch (categoryId) {
				case 1:
					Double bloodOxygen = contentJson.get("bloodOxygen").getAsDouble();
					url = MessageFormat.format(evn.getProperty("config.remote_sync_bldOx_url"), valicode);
					parameterMap.put("bloodOx", bloodOxygen);
					break;
				case 2:
					Double systolicPressure = contentJson.get("systolicPressure").getAsDouble();
					Double diastolicPressure = contentJson.get("diastolicPressure").getAsDouble();
					url = MessageFormat.format(evn.getProperty("config.remote_sync_bldPr_url"), valicode);
					parameterMap.put("systolic", systolicPressure);
					parameterMap.put("diastolic", diastolicPressure);
					break;
				case 3:
					Double bloodSugar = contentJson.get("bloodSugar").getAsDouble();
					url = MessageFormat.format(evn.getProperty("config.remote_sync_bldSg_url"), valicode);
					parameterMap.put("bloodSugure", bloodSugar);
					break;
				default:
					logger.info("健康数据categoryId="+categoryId+"，无需同步");
				}
				if(StringUtils.isNotEmpty(url)){
					logger.info("同步健康数据url如下:{}参数如下:{}",url,JSON.toJSONString(parameterMap));
					
					String result = HttpClientUtil.doFormPost(url, parameterMap);
					
					logger.info("同步结果：{}",result);
				}else{
					logger.info("数据无需同步！");
				}
			} catch (Exception e) {
				logger.error("同步用户失败",e);
			}
		}
		return obj;
	}
	

}	